<?php
namespace App\Admin\Controllers\OverSeasIn;

use App\Importer\Delivery\FBAImporter;
use App\Jobs\OverSeasIn\InventoryBoxSyncTrackingNo;
use App\Models\Basics\SysPlat;
use App\Models\Basics\SysPlatAccount;
use App\Models\OverSeasIn\DeliveryTransport;
use App\Util\SerialNo;
use App\Models\Basics\ExpressChannel;
use App\Models\Basics\ExpressCompany;
use App\Models\OverSeasIn\Delivery;
use App\Models\OverSeasIn\DeliveryLogistics;
use App\Models\Inventory\InventoryCn;
use App\Models\OverSeasBa\Warehouse;
use App\Models\Product\ProductSku;
use App\Models\Sys\Logs;
use App\Util\RExcel;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Facades\Admin;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Maatwebsite\Excel\Facades\Excel;
use Symfony\Component\HttpFoundation\File\UploadedFile;
class OSUploadController extends AdminController{

    protected $title = 'CN至海外仓(中转)-发货单上传';

    protected function grid()
    {
        $type = request('type');
        return view('overseas-in.os-upload.index',compact('type'));
    }

    public function upload(Request $request){
        $file = $request->file('source_file');
        if ($file->isValid()) {
            $action = $request->get('action');
            $param = $request->get('param');
            if($param){
                $re = $this->{'_import'.$action}($file,$param);
            }else{
                $re = $this->{'_import'.$action}($file);
            }
            if(is_array($re)) {
                if($re['flag']){
                    admin_toastr('文件：'.$re['data'].' 上传成功！');
                }else{
                    admin_toastr($re['data'],'error');
                }
            }else{
                return $re;
            }
        }else{
            admin_toastr('无效文件！','error');
        }
        return back()->withInput();
    }

    private function _importDelivery(UploadedFile $file,$param){
        $warehouseId = $param['warehouse_id'];
        $areaId = Warehouse::getAreaIdById($warehouseId);
        $isFnsku = $param['is_fnsku'];
        $platId = $param['plat_id']; //平台
        $deliveryType = $param['delivery_type']; //海外仓发货单类型（2：中转）
        return $this->__importDeliveryArea($file,$warehouseId,$areaId,$isFnsku,$platId,$deliveryType);
    }

    private function __importDeliveryArea(UploadedFile $file,$warehouseId,$areaId,$isFnsku,$platId,$deliveryType){
        try{
            $data = Excel::toArray(new FBAImporter(),$file);
            $data = $data[0];
            if(!$data)return ['flag' => false,'data' => '请上传包含有数据的文件！'];
            $errors = [];
            $count = 1;
            $arr = [];
            $items = [];
            $unitPrice = [];
            foreach($data as $row){
                $count++;
                $sku = $row[0] ? trim($row[0]) : '';
                $applyNum = $row[1] ? trim($row[1]) : 0;
                $account = $row[2] ? trim($row[2]) : '';
                $fnSku = $row[3] ? trim($row[3]) : '';
                if(!$sku || !$applyNum || !$account){
                    $errors[$count] = '必填项为空';
                    continue;
                }
                if ($isFnsku == 1) { //贴标
                    if (!$fnSku){
                        $errors[$count] = '贴标单据，FNSKU不能为空';
                    }
                }else{
                    $fnSku = $sku;
                }
                if (!$platId || $platId == 0) {
                    $errors[$count] = $platId.'系统不存在该平台';
                    continue;
                }

                $key = $account.'-'.$fnSku;
                if(!in_array($key,$arr)){
                    $arr[$count] = $key;
                }else{
                    $errors[$count] = '重复记录';
                    continue;
                }
                $accountId = SysPlatAccount::getIdByAccount($account);
                if(!$accountId){
                    $errors[$count] = $account.'系统不存在该账号';
                    continue;
                }
                $ps = ProductSku::getModelByCode($sku);
                if(!$ps){
                    $errors[$count] = $sku.'系统不存在产品';
                    continue;
                }
                if(!array_key_exists($ps->id,$unitPrice)){
                    $unitPrice[$ps->id] = ProductSku::getPuPrice($ps);
                }
                $items[$key] = [
                    'delivery_type' => $deliveryType, //中转
                    'plat_id' => $platId,
                    'account_id' => $accountId,
                    'psku_id' => $ps->id,
                    'fnsku' => $fnSku,
                    'apply_num' => $applyNum,
                    'unit_price' => $unitPrice[$ps->id]
                ];
            }
            if(empty($items)){
                $errors[] = '本次上传文件未能导入系统：无符合条件的数据';
            }

            /********* 验证库存 start***********/
            $applyTotalArr = getArrayValueSum($items); //sku汇总数量
            $inventoryErrors = [];
            foreach ($items as $_key => $_detail){
                $inventory = InventoryCn::query()
                    ->where('area_id',$areaId)
                    ->where('psku_id',$_detail['psku_id'])
                    ->first();
                if (!$inventory) {
                    $inventoryErrors[$_key] = '无站点库存';
                    continue;
                }
                //验证：库存总量是否满足
                $skuApplyTotal = $applyTotalArr[$_detail['psku_id']]; //同一sku的累计总量
                if ($inventory->instant < $skuApplyTotal) {
                    $inventoryErrors[$_key] = '站点库存总量小于发货总数量，当前库存:'.$inventory->instant.',SKU总申发数量为:'.$skuApplyTotal;
                }
                //验证：库存是否满足
                if ($inventory->instant < $_detail['apply_num']) {
                    $inventoryErrors[$_key] = '站点库存不足，差额：'.($_detail['apply_num'] - $inventory->instant);
                    continue;
                }
            }
            if(!empty($inventoryErrors)){
                return RExcel::importResult($inventoryErrors);
            }
            /********* 验证库存 end***********/

            if(empty($errors)){
                DB::beginTransaction();
                $totalSku = 0;
                $totalUnit = 0;
                $_flag = false;
                foreach ($items as $_key => $_detail){
                    $inventory = InventoryCn::query()
                        ->where('area_id',$areaId)
                        ->where('psku_id',$_detail['psku_id'])
                        ->first();
                    if (!$inventory) {
                        $_flag = true;
                        break;
                    }
                    if ($inventory->instant < $_detail['apply_num']) {
                        $_flag = true;
                        break;
                    }
                    $inventory->instant -= $_detail['apply_num'];
                    $inventory->reserve += $_detail['apply_num'];
                    $flag1 = $inventory->save();
                    if(!$flag1){
                        $_flag = true;
                        break;
                    }
                    $totalSku++;
                    $totalUnit += $_detail['apply_num'];
                }
                if($_flag){
                    DB::rollBack();
                    return RExcel::importResult(['库存更新失败']);
                }
                $osd = Delivery::query()->create(
                    [
                        'delivery_no' => SerialNo::getOSDNo(),
                        'plat_id' => $platId,
                        'area_id' => $areaId,
                        'seller_id' => Admin::user()->id,
                        'warehouse_id' => $warehouseId,
                        'total_sku' => $totalSku,
                        'total_unit' => $totalUnit,
                        'is_fnsku' => $isFnsku,
                    ]
                );
                $osd->detail()->createMany($items);
                if($osd){
                    Logs::logs('os-in-delivery',"创建发货单：{$osd->delivery_no}",$osd->id);
                    DB::commit();
                }else{
                    DB::rollBack();
                }
                return ['flag' => true,'data' => $file->getClientOriginalName()];
            }else{
                return RExcel::importResult($errors);
            }
        }catch(\Exception $e){
            DB::rollBack();
            report($e);
            return ['flag' => false,'data' => '系统异常！'];
        }
    }

    /**
     * 运输信息
     * @param UploadedFile $file
     * @return array|\Symfony\Component\HttpFoundation\BinaryFileResponse
     */
    private function _importTransport(UploadedFile $file)
    {
        try {
            $dataO = Excel::toArray(new FBAImporter(),$file);
            $dataO = $dataO[0];
            if(!$dataO)return ['flag' => false,'data' => '请上传包含有数据的文件！'];
            DB::beginTransaction();
            $errors = [];
            $count = 1;
            $arr = [];
            $data = [];
            foreach($dataO as $row){
                $count++;
                $_deliveryNo = $row[0] ? trim($row[0]) : '';
                $_status = $row[1] ? trim($row[1]) : '';
                $dateAt = $row[2] ? RExcel::toDateTime(trim($row[2])) : '';
                if(!$_deliveryNo || !$_status || !$dateAt){
                    $errors[$count] = '必填项为空';
                    continue;
                }
                $deliveryNo = strtoupper($_deliveryNo);
                if(!in_array($_status,DeliveryTransport::$_status)){
                    $errors[$count] = '状态'.$_status.'不存在，请选择'.implode(',',DeliveryTransport::$_status);
                    continue;
                }
                $status = array_search($_status,DeliveryTransport::$_status);
                $key = $deliveryNo.'-'.$status;
                if(!in_array($key,$arr)){
                    $arr[$count] = $key;
                }else{
                    $errors[$count] = '重复记录';
                    continue;
                }
                if(!strtotime($dateAt)){
                    $errors[$count] = "日期：".$dateAt."格式有误";
                    continue;
                }
                $data[$deliveryNo][$status] = date('Y-m-d H:i:s',strtotime($dateAt));
            }
            if(empty($data)){
                $errors[] = '无符合条件的数据';
            }
            if(!empty($errors)){
                return RExcel::importResult($errors);
            }
            foreach ($data as $deliveryNo => $item){
                $d = Delivery::query()->where('delivery_no', $deliveryNo)->first();
                if(!$d){
                    $errors[$deliveryNo] = $deliveryNo.'发货单不存在';
                    continue;
                }
                $max = $d->transport_status ?: 0;
                foreach ($item as $status => $dateAt){
                    if($max < $status){
                        $max = $status;
                    }
                    $transport = DeliveryTransport::query()->firstOrNew(['delivery_no' => $deliveryNo,'status' => $status]);
                    $transport->date_at = $dateAt;
                    $transport->save();
                }
                $d->transport_status = $max;
                $d->save();
            }
            DB::commit();
            if(empty($errors)){
                return ['flag' => true,'data' => $file->getClientOriginalName()];
            }else{
                return RExcel::importResult($errors);
            }
        } catch (\Exception $e) {
            DB::rollBack();
            report($e);
            return ['flag' => false,'data' => '系统异常！'];
        }
    }

    /**
     * 物流信息
     * @param UploadedFile $file
     * @return array|\Symfony\Component\HttpFoundation\BinaryFileResponse
     */
    private function _importLogistics(UploadedFile $file)
    {
        try {
            $data = Excel::toArray(new FBAImporter(),$file);
            $data = $data[0];
            if(!$data)return ['flag' => false,'data' => '请上传包含有数据的文件！'];
            DB::beginTransaction();
            $errors = [];
            $count = 1;
            $arr = [];
            $items = [];
            foreach($data as $row){
                $count++;
                $_deliveryNo = $row[0] ? trim($row[0]) : '';
                $expressCompanyId = $row[1] ? trim($row[1]) : '';
                $expressChannelId = $row[2] ? trim($row[2]) : '';
                $trackingNo = $row[3] ? trim($row[3]) : '';
                $totalWeight = $row[4] ? trim($row[4]) : '';
                $shippingFee = $row[5] ? trim($row[5]) : '';
                $otherFee = $row[6] ? trim($row[6]) : '';
                $arrivedAt = $row[7] ? RExcel::toDateTime(trim($row[7])) : '';
                if(!$_deliveryNo || !$expressCompanyId || !$expressChannelId){
                    $errors[$count] = '必填项为空';
                    continue;
                }
                if(!$trackingNo || !$arrivedAt){
                    $errors[$count] = '必填项为空';
                    continue;
                }

                $deliveryNo = strtoupper($_deliveryNo);
                if(!in_array($deliveryNo,$arr)){
                    $arr[$count] = $deliveryNo;
                }else{
                    $errors[$count] = '重复记录';
                    continue;
                }
                if($arrivedAt){
                    if(!strtotime($arrivedAt)){
                        $errors[$count] = "日期：".$arrivedAt."格式有误";
                        continue;
                    }
                }
                $expressCompanyIdFlag = ExpressCompany::existById($expressCompanyId);
                if(!$expressCompanyIdFlag){
                    $errors[$count] = $expressCompanyId.'系统不存在';
                    continue;
                }
                $expressChannelIdFlag = ExpressChannel::existById($expressChannelId);
                if(!$expressChannelIdFlag){
                    $errors[$count] = $expressChannelId.'系统不存在';
                    continue;
                }
                $pd = Delivery::query()->where('delivery_no', $deliveryNo)->first();
                if(!$pd){
                    $errors[$count] = $_deliveryNo.'发货单不存在';
                    continue;
                }
                $logistics = DeliveryLogistics::query()->firstOrNew(['delivery_no' => $deliveryNo]);
                $logistics->express_company_id = $expressCompanyId;
                $logistics->area_id = $pd->area_id;
                $logistics->express_channel_id = $expressChannelId;
                if($trackingNo){
                    $logistics->tracking_no = $trackingNo;
                }
                if($totalWeight){
                    $logistics->total_weight = $totalWeight;
                }
                if($shippingFee){
                    $logistics->shipping_fee = $shippingFee;
                }
                if($otherFee){
                    $logistics->other_fee = $otherFee;
                }
                if($arrivedAt){
                    $logistics->arrived_at = date('Y-m-d H:i:s',strtotime($arrivedAt));
                }
                $flag1 = $logistics->save();
                if(!$flag1){
                    continue;
                }
                $pd->logistics_status = 2;
                if($logistics->tracking_no){
                    $pd->track_ex_status = 2;//已录入
                    $items[] = $deliveryNo;
                }
                $pd->save();
            }
            DB::commit();
            if(!empty($items)){
                //异常中转单号同步
                InventoryBoxSyncTrackingNo::dispatch($items);
            }
            if(empty($errors)){
                return ['flag' => true,'data' => $file->getClientOriginalName()];
            }else{
                return RExcel::importResult($errors);
            }
        } catch (\Exception $e) {
            DB::rollBack();
            report($e);
            return ['flag' => false,'data' => '系统异常！'];
        }
    }

    /**
     * 批量上传物流追踪号（仓库规格模板上传）
     * @param UploadedFile $file
     * @return array|\Symfony\Component\HttpFoundation\BinaryFileResponse
     */
    private function _importLogisticsTrackingNo(UploadedFile $file)
    {
        $deliveryType = Delivery::OS_DELIVERY_TRANSFER; //海外-中转
        try {
            $data = Excel::toArray(new FBAImporter(),$file);
            $data = $data[0];
            if(!$data)return ['flag' => false,'data' => '请上传包含有数据的文件！'];
            DB::beginTransaction();
            $errors = [];
            $count = 1;
            $trackingNoArr = [];
            foreach($data as $row){
                $count++;
                $_deliveryNo = $row[0] ? trim($row[0]) : '';
                $_trackingNo = $row[1] ? trim($row[1]) : '';
                if(!$_deliveryNo || !$_trackingNo){
                    $errors[$count] = ',必填项为空';
                    continue;
                }
                $deliveryNo = strtoupper($_deliveryNo);
                $deliveryObj = Delivery::query()
                    ->where('delivery_no', $deliveryNo)
                    ->where('delivery_type',$deliveryType)
                    ->first();
                if(!$deliveryObj){
                    $errors[$count] = $_deliveryNo.','.Delivery::$_deliveryType[$deliveryType].'发货单不存在';
                    continue;
                }

                $trackingNoArr[$deliveryNo][] = $_trackingNo; //追踪号集合
            }

            if(empty($errors)){
                foreach ($trackingNoArr as $key => $val){
                    $uniqueArray = array_unique($val); //去重
                    $trackingNos = implode(',',$uniqueArray); //追踪号(字符串)

                    //物流
                    $logistics = DeliveryLogistics::query()->firstOrNew(['delivery_no' => $key]);
                    $logistics->tracking_no = $trackingNos;
                    $flag1 = $logistics->save();
                    if(!$flag1){
                        continue;
                    }

                    $delivery = Delivery::query()->where('delivery_no', $key)->first();
                    if(!$delivery){
                        continue;
                    }
                    //发货单
                    $delivery->logistics_status = 2; //物流已更新
                    if($logistics->tracking_no){
                        $delivery->track_ex_status = 2;//运单号已录入
                    }
                    $flag1 = $delivery->save();
                    if($flag1){
                        DB::commit();
                    }else{
                        DB::rollBack();
                    }
                }

                return ['flag' => true,'data' => $file->getClientOriginalName()];
            }else{
                return RExcel::importResult($errors);
            }

        } catch (\Exception $e) {
            DB::rollBack();
            report($e);
            return ['flag' => false,'data' => '系统异常！'];
        }
    }

    public function template(Request $request){
        $temp = $request->get('temp');
        $suffix = $request->get('suffix','xlsx');
        return Storage::disk('admin')->download("template/{$temp}-template.{$suffix}");
    }
}
